package com.zlzlib.vuePage;

import com.zlzlib.common.bean.EnumVo;
import com.zlzlib.common.util.JacksonUtil;
import com.zlzlib.common.util.SpringContextUtil;
import com.zlzlib.vuePage.annotation.VueTableItem;
import com.zlzlib.vuePage.annotation.data.FormDataEnumField;
import com.zlzlib.vuePage.annotation.data.FormDataField;
import com.zlzlib.vuePage.annotation.data.FormDataFileField;
import com.zlzlib.vuePage.annotation.form.*;
import com.zlzlib.vuePage.bean.dto.DemoFindDto;
import com.zlzlib.vuePage.bean.enums.FormShowTypeEnum;
import com.zlzlib.vuePage.bean.vo.DemoTableVo;
import com.zlzlib.vuePage.bean.vo.FormDataConfigVo;
import com.zlzlib.vuePage.bean.vo.FormItemVo;
import com.zlzlib.vuePage.bean.vo.TableItemVo;
import com.zlzlib.vuePage.config.FormSelectData;
import org.springframework.util.StringUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @DateTime: 2024/5/23 10:54
 * @Author zlz
 * @Version 1.0
 */
public class VuePageUtils {


    public static List<TableItemVo> getTableItemList(Class<?> clazz) {
        List<TableItemVo> list = new ArrayList<>();
        // 遍历所有声明的字段
        for (Field field : getAllDeclaredFields(clazz)) {
            // 获取注解实例
            try {
                // 检查字段是否有VueTableItem注解
                if (field.isAnnotationPresent(VueTableItem.class)) {
                    VueTableItem description = field.getAnnotation(VueTableItem.class);
                    TableItemVo vo = new TableItemVo();
                    vo.setKey(StringUtils.hasLength(description.key()) ?
                            description.key() : field.getName());
                    vo.setTitle(description.title());
                    vo.setAlign(description.align());
                    vo.setShowType(description.showType());
                    vo.setLine(description.line());
                    vo.setIndex(description.index());
                    vo.setWidth(description.width());
                    vo.setWidthType(description.widthType());
                    list.add(vo);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        list.sort(Comparator.comparingInt(TableItemVo::getIndex));
        return list;
    }

    public static Field[] getAllDeclaredFields(Class<?> clazz) {
        Field[] fields = clazz.getDeclaredFields();
        if (clazz.getSuperclass() != null) {
            Field[] superClassFields = getAllDeclaredFields(clazz.getSuperclass());
            Field[] combinedFields = new Field[fields.length + superClassFields.length];
            System.arraycopy(superClassFields, 0, combinedFields, 0, superClassFields.length);
            System.arraycopy(fields, 0, combinedFields, superClassFields.length, fields.length);
            return combinedFields;
        }
        return fields;
    }

    public static List<FormItemVo> getFormItemList(Class<?> clazz) {
        List<FormItemVo> list = new ArrayList<>();
        // 遍历所有声明的字段
        for (Field field : getAllDeclaredFields(clazz)) {
            // 获取注解实例
            try {
                FormItemVo vo = new FormItemVo();
                // 基础数据
                if (field.isAnnotationPresent(FormBaseField.class)) {
                    FormBaseField description = field.getAnnotation(FormBaseField.class);
                    vo.setKey(StringUtils.hasLength(description.key()) ?
                            description.key() : field.getName());
                    vo.setHint(description.hint());
                    vo.setTitle(description.title());
                    vo.setDefaultValue(description.defaultValue());
                    vo.setEdit(description.edit());
                    vo.setPropTip(description.propTip());
                    vo.setDefaultTip(description.defaultTip());
                    list.add(vo);
                }
                //输入框
                if (field.isAnnotationPresent(FormInputField.class)) {
                    vo.setType(FormShowTypeEnum.input);
                    vo.setFormConfig(annotationToMap(field.getAnnotation(FormInputField.class)));
                }
                //单选框
                if (field.isAnnotationPresent(FormRadioButtonField.class)) {
                    vo.setType(FormShowTypeEnum.radioButton);
                    FormRadioButtonField description = field.getAnnotation(FormRadioButtonField.class);
                    getFormDataEnumValue(description.dataField(), vo, field.getName());
                    vo.setFormConfig(annotationToMap(description));
                }
                //下拉选项枚举数据
                if (field.isAnnotationPresent(FormSelectEnumField.class)) {
                    vo.setType(FormShowTypeEnum.select);
                    FormSelectEnumField description = field.getAnnotation(FormSelectEnumField.class);
                    getFormDataEnumValue(description.dataField(), vo, field.getName());
                    vo.setFormConfig(annotationToMap(description));
                }
                //图标选择
                if (field.isAnnotationPresent(FormIconSelectField.class)) {
                    vo.setType(FormShowTypeEnum.icon);
                    vo.setFormConfig(annotationToMap(field.getAnnotation(FormIconSelectField.class)));
                }
                //图片选择
                if (field.isAnnotationPresent(FormImgSelectField.class)) {
                    vo.setType(FormShowTypeEnum.imgSelect);
                    vo.setFormConfig(annotationToMap(field.getAnnotation(FormImgSelectField.class)));
                }
                //数字输入
                if (field.isAnnotationPresent(FormInputNumberField.class)) {
                    vo.setType(FormShowTypeEnum.inputNumber);
                    vo.setFormConfig(annotationToMap(field.getAnnotation(FormInputNumberField.class)));
                }
                //开关
                if (field.isAnnotationPresent(FormSwitchField.class)) {
                    vo.setType(FormShowTypeEnum.switchButton);
                    vo.setFormConfig(annotationToMap(field.getAnnotation(FormSwitchField.class)));
                }
                //文件上传
                if (field.isAnnotationPresent(FormFileUploadField.class)) {
                    vo.setType(FormShowTypeEnum.fileUpload);
                    FormFileUploadField uploadField =
                            field.getAnnotation(FormFileUploadField.class);
                    vo.setFormConfig(annotationToMap(uploadField));
                    getFormDataFileValue(uploadField.dataFiled(), vo);
                }
                //图片单个上传
                if (field.isAnnotationPresent(FormImgSingleUploadField.class)) {
                    vo.setType(FormShowTypeEnum.imgSingleUpload);
                    FormImgSingleUploadField uploadField =
                            field.getAnnotation(FormImgSingleUploadField.class);
                    vo.setFormConfig(annotationToMap(uploadField));
                    getFormDataFileValue(uploadField.dataFiled(), vo);
                }
                //图片列表上传
                if (field.isAnnotationPresent(FormImgListUploadField.class)) {
                    vo.setType(FormShowTypeEnum.imgListUpload);
                    FormImgListUploadField uploadField =
                            field.getAnnotation(FormImgListUploadField.class);
                    vo.setFormConfig(annotationToMap(uploadField));
                    getFormDataFileValue(uploadField.dataFiled(), vo);
                }
                //表格数据输入
                if (field.isAnnotationPresent(FormTableInputField.class)) {
                    vo.setType(FormShowTypeEnum.inputTable);
                    vo.setFormConfig(annotationToMap(field.getAnnotation(FormTableInputField.class)));
                }
                //json数据输入
                if (field.isAnnotationPresent(FormJsonInputField.class)) {
                    vo.setType(FormShowTypeEnum.inputJson);
                    vo.setFormConfig(annotationToMap(field.getAnnotation(FormJsonInputField.class)));
                }
                //代码数据输入
                if (field.isAnnotationPresent(FormCodeInputField.class)) {
                    vo.setType(FormShowTypeEnum.inputCode);
                    FormCodeInputField formCodeInputField = field.getAnnotation(FormCodeInputField.class);
                    FormDataConfigVo configVo = new FormDataConfigVo();
                    putFormSelectData(configVo, formCodeInputField.demoDataClass(), "");
                    vo.setDataConfig(configVo);
                    vo.setFormConfig(annotationToMap(formCodeInputField));
                }
                //下拉选项
                if (field.isAnnotationPresent(FormSelectField.class)) {
                    vo.setType(FormShowTypeEnum.select);
                    FormSelectField description = field.getAnnotation(FormSelectField.class);
                    getFormDataValue(description.dataField(), vo, field.getName());
                    vo.setFormConfig(annotationToMap(description));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return list;
    }

    private static void getFormDataEnumValue(FormDataEnumField field, FormItemVo vo, String name) {
        FormDataConfigVo configVo = new FormDataConfigVo();
        configVo.setData(EnumVo.getEnumList(field.dataClass().getEnumConstants()));
        configVo.setDataKey(StringUtils.hasLength(field.dataKey()) ?
                field.dataKey() : name + "EnumList");
        configVo.setAddEmpty(field.addEmpty());
        vo.setDataConfig(configVo);
    }

    private static void getFormDataValue(FormDataField field, FormItemVo vo, String name) {
        FormDataConfigVo configVo = new FormDataConfigVo();
        configVo.setDataKey(StringUtils.hasLength(field.dataKey()) ?
                field.dataKey() : name + "DataList");
        configVo.setAddEmpty(field.addEmpty());
        //如果不是子类初始化自己的值
        if (!field.isChild()) {
            putFormSelectData(configVo, field.selfClass(), field.dataFind());
        }
        //初始化子类获取的值
        if (field.isParent()) {
            configVo.setDataChildKey(StringUtils.hasLength(field.dataChildKey()) ?
                    field.dataChildKey() : name + "DataChildList");
            configVo.setChildDataClass(field.childClass().getName());
            configVo.setDataChildValueKey(field.dataChildValueKey());
        }
        vo.setDataConfig(configVo);
    }

    private static void putFormSelectData(FormDataConfigVo configVo,
                                          Class<? extends FormSelectData> cls, String dataFind) {
        try {
            FormSelectData selectData = SpringContextUtil.getBean(cls);
            configVo.setData(selectData.findConditionList(dataFind));
        } catch (Exception ignored) {
        }
    }

    private static void getFormDataFileValue(FormDataFileField field, FormItemVo vo) {
        FormDataConfigVo configVo = new FormDataConfigVo();
        configVo.setFileType(field.fileType());
        configVo.setFilePath(field.filePath());
        configVo.setFileNameKey(field.fileNameKey());
        configVo.setEmptyName(field.emptyName());
        vo.setDataConfig(configVo);
    }

    public static Map<String, Object> annotationToMap(Annotation annotation) {
        Map<String, Object> map = new LinkedHashMap<>();
        Class<? extends Annotation> annotationType = annotation.annotationType();
        for (Method method : annotationType.getDeclaredMethods()) {
            Class<FormDataEnumField> dataEnumClass = FormDataEnumField.class;
            if (dataEnumClass.equals(method.getReturnType())) {
                continue;
            }
            Class<FormDataField> dataClass = FormDataField.class;
            if (dataClass.equals(method.getReturnType())) {
                continue;
            }
            Class<FormDataFileField> fileFieldClass = FormDataFileField.class;
            if (fileFieldClass.equals(method.getReturnType())) {
                continue;
            }
            try {
                map.put(method.getName(), method.invoke(annotation));
            } catch (ReflectiveOperationException e) {
                e.printStackTrace();
            }
        }
        return map;
    }

    public static void main(String[] args) {
        System.out.println(VuePageUtils.getTableItemList(DemoTableVo.class));
        System.out.println(JacksonUtil.toJsonString(getFormItemList(DemoFindDto.class)));
    }
}
